package labox.innovation.gameserver.datatables;

import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javolution.util.FastMap;
import labox.innovation.config.Config;
import labox.innovation.db.core.L2DatabaseFactory;
import labox.innovation.gameserver.model.FuzeTeleportLocation;
import labox.innovation.gameserver.model.FuzeWorld;
import labox.innovation.gameserver.model.Scene;

/**
 * This class ...
 *
 * @version $Revision: 1.3.2.2.2.3 $ $Date: 2005/03/27 15:29:18 $
 */
public class TeleportLocationTable {

	private static final Logger _log = LoggerFactory.getLogger(TeleportLocationTable.class.getName());

	private Map<Integer, FuzeTeleportLocation> _teleports;

	public static TeleportLocationTable getInstance() {
		return SingletonHolder._instance;
	}

	private TeleportLocationTable() {
		reloadAll();
	}

	public void reloadAll() {
		_teleports = new FastMap<Integer, FuzeTeleportLocation>();
		FileInputStream fin = null;
		NodeList nl;
		try {

			File f = new File(Config.DATAPACK_ROOT, "/WorldMap/worldmap.xml");
			fin = new FileInputStream(f);
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document document = builder.parse(fin);
			Element root;
			root = document.getDocumentElement();
			if (root.getTagName().compareTo("WorldMap") != 0) {
				throw new Exception("Not a WorldMap file!");
			}

			nl = root.getElementsByTagName("Scene");
			for (int i = -1; ++i < nl.getLength();) {
				Element ee = (Element) nl.item(i);
				int id = Integer.parseInt(ee.getAttribute("id"));
				if (id < 0)
					continue;
				Scene s = FuzeWorld.getInstance().getScene(id);
				if (s == null) {
					_log.warn("TeleportLocationTable: Error loading Scene data.Not Found id " + id, Config.SERVER_ID, "传送");
					continue;
				}
				s.setName(ee.getAttribute("name"));
				s.setDisc(ee.getAttribute("disc"));
				s.setCanPk(Integer.parseInt(ee.getAttribute("pk")) == 0);
				
				s.setHumanReviveScene(Integer.parseInt(ee.getAttribute("humanReviveScene")));
				s.setHumanRevive2X(Integer.parseInt(ee.getAttribute("humanReviveX")), Integer.parseInt(ee.getAttribute("humanReviveY")));
				
				s.setELFReviveScene(Integer.parseInt(ee.getAttribute("ELFReviveScene")));
				s.setELFRevive2X(Integer.parseInt(ee.getAttribute("ELFReviveX")), Integer.parseInt(ee.getAttribute("ELFReviveY")));
				
				s.setTele2XY(Integer.parseInt(ee.getAttribute("teleX")), Integer.parseInt(ee.getAttribute("teleY")));
				s.setSexRestrict(Integer.parseInt(ee.getAttribute("sex")));
				s.setScreenX(Integer.parseInt(ee.getAttribute("screenX")));
				s.setScreenX(Integer.parseInt(ee.getAttribute("screenY")));
				
				String item = ee.getAttribute("item");
				if (item.length() > 0) {
					String[] items = item.split(";");
					int[] itemR = new int[items.length * 2];
					for (int j = -1; ++j < items.length;) {
						String[] it = items[j].split(",");
						itemR[j * 2] = Integer.parseInt(it[0]);
						itemR[j * 2 + 1] = Integer.parseInt(it[1]);
					}
					s.setItemRestrict(itemR);
				}
				String clas = ee.getAttribute("class");
				if (clas.length() > 0) {
					String[] classes = clas.split(",");
					int[] classR = new int[classes.length];
					for (int j = -1; ++j < classR.length;) {
						classR[j] = Integer.parseInt(classes[0]);
					}
				}
				s.setExpRate(Float.parseFloat(ee.getAttribute("exp")));
				if (Integer.parseInt(ee.getAttribute("timer")) == 0) {
					s.setActive(true);
				} else {
					//设置开放的周期
					s.setCycle(Long.parseLong(ee.getAttribute("cycle")) * getUnit2Millis(Integer.parseInt(ee.getAttribute("cycleUnit"))));
					//设置开发持续的时间
					s.setDuration(Long.parseLong(ee.getAttribute("run")) * getUnit2Millis(Integer.parseInt(ee.getAttribute("runUnit"))));
					//设置首次开放的时间
					s.setFirstStartTime(Long.parseLong(ee.getAttribute("startTime")) - System.currentTimeMillis());
					//解析是否启用关闭场景时传送玩家离开
					if (Integer.parseInt(ee.getAttribute("teleforInactive")) != 0) {
						s.setTeleport2SceneInactive(Integer.parseInt(ee.getAttribute("tele2SceneforInactive")));
						s.setTeleport2XYInactive(Integer.parseInt(ee.getAttribute("tele2XforInactive")), Integer.parseInt(ee.getAttribute("tele2YforInactive")));
					}
				}
			}

			nl = root.getElementsByTagName("Road");

			FuzeTeleportLocation teleport;

			for (int i = -1; ++i < nl.getLength();) {
				Element ee = (Element) nl.item(i);
				teleport = new FuzeTeleportLocation();

				teleport.setTeleId(Integer.parseInt(ee.getAttribute("p1_exid")));
				teleport.setSceneId(Integer.parseInt(ee.getAttribute("p1_movid")));
				teleport.setLocX(Integer.parseInt(ee.getAttribute("p1_movx")));
				teleport.setLocY(Integer.parseInt(ee.getAttribute("p1_movy")));
				_teleports.put(teleport.getTeleId(), teleport);

				teleport = new FuzeTeleportLocation();

				teleport.setTeleId(Integer.parseInt(ee.getAttribute("p2_exid")));
				teleport.setSceneId(Integer.parseInt(ee.getAttribute("p2_movid")));
				teleport.setLocX(Integer.parseInt(ee.getAttribute("p2_movx")));
				teleport.setLocY(Integer.parseInt(ee.getAttribute("p2_movy")));
				_teleports.put(teleport.getTeleId(), teleport);
			}
			_log.info("TeleportLocationTable: Loaded " + _teleports.size() + " Teleport Location Templates.", Config.SERVER_ID, "传送");
		} catch (Exception e) {
			_log.error("Error loading Teleport Table.", Config.SERVER_ID, e);
		} finally {
			if (fin != null) {
				try {
					fin.close();
				} catch (Exception e2) {
					// TODO: handle exception
				}
			}

		}
	}

	private static final int MINUTE = 0;

	private static final int HOUR = 1;

	private static final int DAY = 2;

	private static final int WEEK = 3;

	private static final int MONTH = 4;

	public long getUnit2Millis(int unit) {
		switch (unit) {
		case MINUTE:
			return 60 * 1000L;
		case HOUR:
			return 3600 * 1000L;
		case DAY:
			return 24 * 3600 * 1000L;
		case WEEK:
			return 7 * 24 * 3600 * 1000L;
		case MONTH:
			return 30 * 7 * 24 * 3600 * 1000L;
		default:
			return -1;
		}
	}

	/**
	 * @param template id
	 * @return
	 */
	public FuzeTeleportLocation getTemplate(int id) {
		return _teleports.get(id);
	}

	@SuppressWarnings("synthetic-access")
	private static class SingletonHolder {
		protected static final TeleportLocationTable _instance = new TeleportLocationTable();
	}
}
